#include <string>
#include <list>
#include <atomic>
#include <thread>

#include <hude/base/log.hpp>
#include <hude/utils/parses.hpp>
#include <hude/safe/crc.hpp>

#include "plugs/plug.hpp"

namespace ha
{
    namespace brick
    {
        namespace pl =  std::placeholders;

        /*********************************************************************
         * @brief 虚拟gps模块
         */
        class gps_t :
            public brick_t
        {
        public:
            gps_t( aio_t aio, const json_t& args )
            {
                if( ! this->settings( args ) || !init() )
                {
                    llog_err( "<plug-gps>", "ERROR: pulg init: gps" );
                }
            }

            ~gps_t()
            {
                deinit();
            }

            int send( const void* p, size_t n ) override { return 0; }

            void close() override { deinit(); }

            bool settings( const json_t& args ) override;

        private:
            bool init();
            void deinit();

        private:
            std::atomic< uint32_t > running_;
            std::thread             thread_;
            hude::buffer_t          content_;
        };

        /*********************************************************************
         * @brief 设置参数
         */
        inline bool gps_t::settings( const json_t& args )
        {
            // llog_dug( "<plug-gps>", "\t\t config rfid: %s", args.dump().c_str() );

            if( ! args.is_object() ) return false;

            auto contents = hude::utils::json_path_t::value< std::list< std::string > >( args, "gps" );
            auto interval = hude::utils::json_path_t::value_or_default< size_t >( args, 10 * 1000U, "interval" );

            if( contents )
            {
                content_.clear();

                for( const auto& item : *contents )
                {
                    if( ! content_.empty() ) content_.push_back( '\n' );
                    std::copy( item.begin(), item.end(), std::back_inserter( content_ ) );
                }
            }

            running_ = interval;

            return true;
        }

        /*********************************************************************
         * @brief 初始化
         */
        bool gps_t::init()
        {
            if( thread_.joinable() ) return false;

            // 解析栈工作线程，开始解析栈循环
            thread_ = std::thread{ [=]() {
                while( running_ != 0 )
                {
                    if( this->cb_recv_ )
                    {
                        this->cb_recv_( content_ );
                    }

                    std::this_thread::sleep_for( std::chrono::milliseconds( (uint32_t)running_ ) );
                }
            } };

            return true;
        }

        /*********************************************************************
         * @brief 反初始化
         */
        void gps_t::deinit()
        {
            if( thread_.joinable() )
            {
                thread_.join();
            }
        }

    } //namespace brick
} //namespace ha

/*********************************************************************
 * @brief 工厂函数 
 */
EXTERN_C ha::pbrick_t _factory_brick( ha::aio_t aio, const ha::json_t& cfg )
{
    return ha::pbrick_t( new ha::brick::gps_t{ aio, cfg } );
}